﻿using System;
using PureMVC.Patterns;
using GameEngine.View.Components;
using System.Collections.Generic;
using GameEditor.View.Components;
using System.Windows;
using GameEngine.Model.Data;
using PureMVC.Interfaces;
using GameEngine.Model;
using System.Windows.Input;
using GameEngine.View;
using GameEngine;
using MapEngine;

namespace GameEditor.View
{
    public class MapPropertiesEditor_Mediator<MyIdType> : Mediator
        where MyIdType : IComparable<MyIdType>
    {
        IMapDataProxy<MyIdType> dataProxy;
        //MapMediator<MyMapView, MyThingView, MyIdType, MyBaseUIElementType> mapMediator;
        //public readonly String TERRAINUP_BUTTONPRESSED = "TileMapEditorMenuMediator_TerrainUp_";
        //public readonly String TERRAINDOWN_BUTTONPRESSED = "TileMapEditorMenuMediator_TerrainDown_";
        //public readonly String SETMAPPROPERTIES_BUTTONPRESSED = "TileMapEditorMenuMediator_SetMapProperties_";
        //public readonly String GENERATEMAPHEIGHTS_BUTTONPRESSED = "TileMapEditorMenuMediator_GenerateMapHeights_";
        //public readonly String SIZECHANGED = "TileMapEditorMenuMediator_SizeChanged_";

        public MapPropertiesEditor_Mediator(string name,IMapEditorMenuView view, IMapDataProxy<MyIdType> dataProxy)
            : base(name, view)
        {
            //TERRAINUP_BUTTONPRESSED += name;
            //TERRAINDOWN_BUTTONPRESSED += name;
            //SETMAPPROPERTIES_BUTTONPRESSED += name;
            //GENERATEMAPHEIGHTS_BUTTONPRESSED += name;
            //SIZECHANGED += name;
            //ViewComponentGenerator = viewGenerator;
            this.dataProxy = dataProxy;
            //this.mapMediator = mapMediator;
        }

        public new IMapEditorMenuView ViewComponent
        {
            get { return base.ViewComponent as IMapEditorMenuView; }
        }

        #region IMediator Members

        /// <summary>
        /// List the <c>INotification</c> names this <c>Mediator</c> is interested in being notified of
        /// </summary>
        /// <returns>The list of <c>INotification</c> names </returns>
        override public IList<string> ListNotificationInterests()
        {
            IList<String> notifications = base.ListNotificationInterests();
            notifications.Add(MapMediatorConstants<MyIdType>.TILEMOUSELEFTBUTTONUP);
            return notifications;
        }

        /// <summary>
        /// Handle <c>INotification</c>s
        /// </summary>
        /// <param name="notification">The <c>INotification</c> instance to handle</param>
        /// <remarks>
        ///     <para>
        ///        Typically this will be handled in a switch statement, with one 'case' entry per <c>INotification</c> the <c>Mediator</c> is interested in. 
        ///     </para>
        /// </remarks>
        override public void HandleNotification(INotification notification)
        {
            switch (notification.Name)
            {
                case MapMediatorConstants<MyIdType>.TILEMOUSELEFTBUTTONUP:
                    Point position = (Point)notification.Body;
                    if (TerrainDownButtonPressed)
                    {
                        TerrainDown(position);
                    }
                    if (TerrainUpButtonPressed)
                    {
                        TerrainUp(position);
                    }
                    break;
                default:
                    break;
            }

            base.HandleNotification(notification);
                
        }

        /// <summary>
        /// Called by the View when the Mediator is registered
        /// </summary>
        override public void OnRegister()
        {
            ViewComponent.OnMapGenerateHeights += new Action<object>(ViewComponent_OnMapGenerateHeights);
            ViewComponent.OnMapPropertiesSet += new Action<object>(ViewComponent_OnMapPropertiesSet);
            ViewComponent.OnTerrainDown += new Action<object>(ViewComponent_OnTerrainDown);
            ViewComponent.OnTerrainUp += new Action<object>(ViewComponent_OnTerrainUp);

            ViewComponent.MapSize = dataProxy.Size;
            ViewComponent.TileType = dataProxy.TileType;
            ViewComponent.MapType = dataProxy.MapType;
            ViewComponent.PerlinFrequency = 0.025f;//mais terra 0.005
            ViewComponent.PerlinAmplitude = 1f;//mais no limite
            ViewComponent.PerlinPersistence = 0.5f;//mais suave
            ViewComponent.PerlinOctaves = 2;
            ViewComponent.PerlinSeed = 1;
            ViewComponent.PerlinOrigin = new Point();
        }

        /// <summary>
        /// Called by the View when the Mediator is removed
        /// </summary>
        override public void OnRemove()
        {
            
        }

        #endregion

        #region View Members

        void ViewComponent_OnTerrainUp(object obj)
        {
            //SendNotification(TERRAINUP_BUTTONPRESSED);
            if (TerrainUpButtonPressed)
                dataProxy.Cursor=Cursors.Hand;
            else
                dataProxy.Cursor=Cursors.Arrow;
        }

        void ViewComponent_OnTerrainDown(object obj)
        {
            //SendNotification(TERRAINDOWN_BUTTONPRESSED);
            if (TerrainDownButtonPressed)
                dataProxy.Cursor=Cursors.Hand;
            else
                dataProxy.Cursor=Cursors.Arrow;
        }

        void ViewComponent_OnMapPropertiesSet(object obj)
        {
            //SendNotification(SETMAPPROPERTIES_BUTTONPRESSED);
            dataProxy.Cursor=Cursors.Arrow;
            dataProxy.TileType = TileType;
            dataProxy.MapType = MapType;
            dataProxy.CreateTiles(MapSize);
            dataProxy.CameraPosition = new Point(Math.Round(MapSize.X/2),Math.Round(MapSize.Y/2));
        }

        void ViewComponent_OnMapGenerateHeights(object obj)
        {
            //SendNotification(GENERATEMAPHEIGHTS_BUTTONPRESSED);
            dataProxy.Cursor=Cursors.Arrow;

            dataProxy.GenerateHeightsFromPerlin(
                PerlinOrigin,
                PerlinFrequency,
                PerlinAmplitude,
                PerlinPersistence,
                PerlinOctaves,
                PerlinSeed);
        }
        
        #endregion

        void TerrainUp(Point position)
        {
            var gameDataProxy = ModelFacade<MyIdType>.Instance.Game;
            ITileVO tile = dataProxy.GetTile(position);
            if (tile != null)
            {
                float newHeightValue = tile.Height + gameDataProxy.TileHeightUnit;
                if (newHeightValue > gameDataProxy.MaxHeight)
                    newHeightValue = gameDataProxy.MaxHeight;
                dataProxy.SetTileHeight(position, newHeightValue);
            }
        }

        void TerrainDown(Point position)
        {
            var gameDataProxy = ModelFacade<MyIdType>.Instance.Game;
            ITileVO tile = dataProxy.GetTile(position);
            if (tile != null)
            {
                float newHeightValue = tile.Height - gameDataProxy.TileHeightUnit;
                if (newHeightValue < gameDataProxy.MinHeight)
                    newHeightValue = gameDataProxy.MinHeight;
                dataProxy.SetTileHeight(position, newHeightValue);
            }
        }


        public Point MapSize
        {
            get { return ViewComponent.MapSize; }
            set { ViewComponent.MapSize = value; }
        }
        public TileType TileType
        {
            get { return ViewComponent.TileType; }
            set { ViewComponent.TileType = value; }
        }
        public MapType MapType
        {
            get { return ViewComponent.MapType; }
            set { ViewComponent.MapType = value; }
        }
        
        public float PerlinFrequency{
            get { return ViewComponent.PerlinFrequency; }
            set { ViewComponent.PerlinFrequency = value; }
        }
        public float PerlinAmplitude{
            get { return ViewComponent.PerlinAmplitude; }
            set { ViewComponent.PerlinAmplitude = value; }
        }
        public float PerlinPersistence{
            get { return ViewComponent.PerlinPersistence; }
            set { ViewComponent.PerlinPersistence = value; }
        }
        public int PerlinOctaves{
            get { return ViewComponent.PerlinOctaves; }
            set { ViewComponent.PerlinOctaves = value; }
        }
        public int PerlinSeed{
            get { return ViewComponent.PerlinSeed; }
            set { ViewComponent.PerlinSeed = value; }
        }
        public Point PerlinOrigin{
            get { return ViewComponent.PerlinOrigin; }
            set { ViewComponent.PerlinOrigin = value; }
        }
        public bool TerrainDownButtonPressed
        {
            get { return ViewComponent.TerrainDownButtonPressed; }
        }
        public bool TerrainUpButtonPressed
        {
            get { return ViewComponent.TerrainUpButtonPressed; }
        }
    }
}